// SPDX-License-Identifier: MIT

@use "../settings/config" as cfg;
@use "../settings/icons";

$color-cell-bg:                  -color-bg-default !default;
$color-cell-fg:                  -color-fg-default !default;
$color-cell-bg-selected:         if(cfg.$darkMode, -color-base-6, -color-base-1) !default;
$color-cell-fg-selected:         -color-fg-default !default;
$color-cell-bg-selected-focused: $color-cell-bg-selected !default;
$color-cell-fg-selected-focused: $color-cell-fg-selected !default;
$color-cell-bg-odd:              -color-bg-subtle      !default;
$color-cell-border:              -color-border-default !default;
$color-disclosure:               -color-fg-muted       !default;

$color-header-bg: -color-bg-subtle  !default;
$color-header-fg: -color-fg-default !default;

$color-resize-line:  -color-accent-emphasis !default;
$color-drag-header:  -color-accent-muted    !default;
$color-drag-overlay: -color-accent-muted    !default;

// warning: setting header size in 'em' sometimes breaks borders
$header-size-normal: 40px !default;
$header-size-dense: 34px  !default;

$cell-size-normal: 2.8em !default;
$cell-size-dense:  2em   !default;
$cell-padding-x:   0.5em !default;

// .tree-cell doesn't support -fx-cell-size,
// its height should be set via vertical paddings
$tree-cell-padding-x:        0.5em  !default;
$tree-cell-padding-y-normal: 0.5em  !default;
$tree-cell-padding-y-dense:  0.25em !default;

// This variable is for '-fx-indent' manipulation. Ideally, each descendant disclosure
// node should be aligned with its ancestor text (graphic) start position. Like this:
//
// > ⬛ foo
//   > ⬛ bar
//     > ⬛ baz
//
// Sadly, JavaFX doesn't do this programmaticaly and with CSS it's not possible
// to define universal indentation size that would look perfect with any disclosure
// icon or cell graphic icon, because any icon have its own margins or you may not
// use icon at all.
//
// If you feel that your tree cell content isn't aligned properly, play with
// '-fx-indent' and left '.tree-cell' padding.
$tree-cell-indent: 1.2em !default; // default JavaFX values is 18px

@mixin _base() {

  -color-cell-bg: $color-cell-bg;
  -color-cell-fg: $color-cell-fg;
  -color-cell-bg-selected: $color-cell-bg-selected;
  -color-cell-fg-selected: $color-cell-fg-selected;
  -color-cell-bg-selected-focused: $color-cell-bg-selected-focused;
  -color-cell-fg-selected-focused: $color-cell-fg-selected-focused;
  -color-cell-bg-odd: $color-cell-bg-odd;
  -color-cell-border: $color-cell-border;
  -color-disclosure:  $color-disclosure;

  -fx-border-color: -color-cell-border;
  -fx-border-width: cfg.$border-width;
  -fx-border-radius: 0;

  >.virtual-flow {
    >.corner {
      -fx-background-color: -color-cell-border;
      -fx-opacity: cfg.$opacity-disabled;
    }

    // apply opacity to all but control borders
    &:disabled {
      -fx-opacity: cfg.$opacity-disabled;
    }
  }

  // #tweak/edge-to-edge
  &.edge-to-edge {
    -fx-border-width: 0;
  }
}

// row selection (cellSelectionEnabled = false)
.list-view>.virtual-flow>.clipped-container>.sheet>.list-cell:filled:selected,
.tree-view>.virtual-flow>.clipped-container>.sheet>.tree-cell:filled:selected,
.table-view>.virtual-flow>.clipped-container>.sheet>.table-row-cell:filled:selected,
.tree-table-view>.virtual-flow>.clipped-container>.sheet>.tree-table-row-cell:filled:selected {
  -color-cell-fg: -color-cell-fg-selected;
  -fx-background-color: -color-cell-border, -color-cell-bg-selected;
}
.list-view:focused>.virtual-flow>.clipped-container>.sheet>.list-cell:filled:selected,
.tree-view:focused>.virtual-flow>.clipped-container>.sheet>.tree-cell:filled:selected,
.table-view:focused>.virtual-flow>.clipped-container>.sheet>.table-row-cell:filled:selected,
.tree-table-view:focused>.virtual-flow>.clipped-container>.sheet>.tree-table-row-cell:filled:selected {
  -color-cell-fg: -color-cell-fg-selected-focused;
  -fx-background-color: -color-cell-border, -color-cell-bg-selected-focused;
}

// individual cell selection (cellSelectionEnabled = true)
.table-view>.virtual-flow>.clipped-container>.sheet>.table-row-cell .table-cell:selected,
.tree-table-view>.virtual-flow>.clipped-container>.sheet>.tree-table-row-cell .tree-table-cell:selected {
  -fx-background-color: -color-cell-bg-selected;
  // a margin to show bottom .table-row-cell border,
  // it should be 1px height, but for some reason it's not enough
  -fx-background-insets: 0 0 2 0;
}
.table-view:focused>.virtual-flow>.clipped-container>.sheet>.table-row-cell .table-cell:selected,
.tree-table-view:focused>.virtual-flow>.clipped-container>.sheet>.tree-table-row-cell .tree-table-cell:selected {
  -fx-background-color: -color-cell-bg-selected-focused;
}

///////////////////////////////////////////////////////////////////////////////
//  Customised CSS for controls placed directly within cells                 //
///////////////////////////////////////////////////////////////////////////////

// nested controls supposed to have nor background nor borders
.cell {

  // NOTE:
  // The controls inside .tree-cell _with graphic_ will be wrapped into additional
  // container that don't use hgrow and adjusts its width after showing popup.
  // It looks rather ugly, but there's nothing could be fixed with CSS.
  // That's also why we don't use child combinator here.
  // #javafx-bug

  .text-input {
    -fx-background-color: transparent;
    -fx-background-insets: 0;
    -fx-background-radius: 0;
    -fx-padding: 0;
  }

  .check-box {
    -fx-padding: 0 cfg.$graphic-gap 0 0;
  }

  .choice-box {
    -fx-background-color: transparent;
    -fx-background-insets: 0;
    -fx-background-radius: 0;
    -fx-padding: 0 cfg.$padding-x 0 0;
    -fx-alignment: CENTER_LEFT;
    -fx-content-display: LEFT;
  }

  .combo-box {
    -fx-background-color: transparent;
    -fx-alignment: CENTER_LEFT;
    -fx-content-display: LEFT;
    -fx-background-radius: 0;

    // must be more specific than ".list-view .list-cell" selector (see below)
    .cell.list-cell {
      -fx-background-color: transparent;
      -fx-padding: 0;
      -fx-background-insets: 0;
      -fx-background-radius: 0;
    }
  }
}

// The styles for focused editable cells. For now only TextFieldTableCell is supported,
// because all other editable cells are bugged. #javafx-bug
// - ChoiceBoxTableCell - does not support :focus-within
// - ComboBoxTableCell - inconsistently activates :focus-within after popup is shown (virtually useless)
// - TextFieldListCell - activates :focus-within when TextField is not in editable state (same as focused, virtually useless)
// .. too lazy check further, generally all editable cells is a compilation of bugs.
.table-view>.virtual-flow>.clipped-container>.sheet>.table-row-cell .text-field-table-cell:focus-within {
  -fx-background-insets: 0, 1, 2;
  -fx-background-color: -color-bg-default, -color-accent-emphasis, -color-bg-default;
}

///////////////////////////////////////////////////////////////////////////////
//  ListView                                                                 //
///////////////////////////////////////////////////////////////////////////////

.list-view {

  @include _base();

  .list-cell {
    -fx-background-color: -color-cell-bg;
    -fx-text-fill: -color-cell-fg;
    -fx-padding: 0 $cell-padding-x 0 $cell-padding-x;
    -fx-cell-size: $cell-size-normal;

    // there's no ":first" or ":last" cell pseudo classes,
    // so we can't avoid double border at the bottom
    -fx-border-width: 0 0 1 0;
    -fx-border-color: transparent;
  }

  &.bordered {
    .list-cell {
      -fx-border-color: -color-cell-border;

      &:empty {
        -fx-border-color: transparent;
      }
    }
  }

  &.dense {
    .list-cell {
      -fx-cell-size: $cell-size-dense;
    }
  }

  &.striped {
    .list-cell {
      -fx-border-width: 0;
    }

    .list-cell:filled:odd {
      -fx-background-color: -color-cell-bg-odd;
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
//  TableView                                                                //
///////////////////////////////////////////////////////////////////////////////

@mixin _generic-table {

  @include _base();

  -color-header-bg: $color-header-bg;
  -color-header-fg: $color-header-fg;

  &.bordered {
    >.column-header-background {
      .column-header {
        -fx-background-color: -color-cell-border, -color-header-bg;
        -fx-background-insets: 0, 0 1 0 0;
      }
    }
  }

  // the column header row is made up of a number of .column-header, one for each TableColumn
  >.column-header-background {

    -fx-background-color: -color-cell-border, -color-header-bg;
    -fx-background-insets: 0, 0 0 1 0;

    // there's also
    // .nested-column-header { }

    // columns headers can be nested, so there's no child combinator here
    .column-header {
      -fx-background-color: transparent;
      -fx-background-insets: 0;
      -fx-size: $header-size-normal;
      -fx-padding: 0;
      -fx-font-weight: bold;
      -fx-border-color: -color-cell-border;
      -fx-border-width: 0 1 1 0;

      // any label within column header, including title and sort order label
      .label {
        -fx-text-fill: -color-header-fg;
        -fx-alignment: CENTER_LEFT;
        -fx-padding: 0 $cell-padding-x 0 $cell-padding-x;
      }

      // sort container
      GridPane {
        -fx-padding: 0 4px 0 0;
      }

      // column sort arrows
      .arrow {
        -fx-background-color: -color-header-fg;
        -fx-padding: 3px 4px 3px 4px;
        -fx-shape: "M 0 0 h 7 l -3.5 4 z";
      }

      // dots are used to indicate up to 3 multiple sort columns
      .sort-order-dots-container {
        -fx-padding: 2px 0 2px 0;

        >.sort-order-dot {
          -fx-background-color: -color-header-fg;
          -fx-padding: 0.115em;
          -fx-background-radius: 0.115em;
        }
      }

      // digits are used to indicate more than 3 multiple sort columns
      .sort-order {
        -fx-padding: 0 0 0 2px;
      }
    }

    // .filler area extends from the right-most column to the edge of the table view
    >.filler {
      -fx-background-color: transparent;
      -fx-border-color: -color-cell-border;
      -fx-border-width: 0 0 1 0;
    }

    // table menu button
    >.show-hide-columns-button {
      -fx-border-color: -color-cell-border;
      -fx-border-width: 0 0 1 0;
      -fx-cursor: hand;

      // NOTE:
      // If you want to increase right margin you should take into account
      // that it's harder than it looks. E.g. paddings, transparent insets or borders
      // aren't working. Just be sure you have enough time to tackle this problem.

      >.show-hide-column-image {
        -fx-background-color: -color-header-fg;
        @include icons.get("more-vert", true);
        -fx-padding: 0.4em 0.115em 0.4em 0.115em;
      }
    }
  }

  // the .column-resize-line is shown when the user is attempting to resize a column
  .column-resize-line {
    -fx-background-color: $color-resize-line;
    -fx-padding: 0 1 0 1;
  }

  // when a column is being dragged to be placed in a different position, there is a region
  // that follows along the column header area to indicate where the column will be dropped
  .column-drag-header {
    // -color-accent-muted must be RGBA color for this to work, because
    // applying opacity to the whole pane makes label text unreadable
    -fx-background-color: $color-drag-header;
  }

  // semi-transparent overlay to indicate the column that is currently being moved
  .column-overlay {
    -fx-background-color: $color-drag-overlay;
  }

  // this is shown when the table has no rows and/or no columns
  .placeholder>.label {
    -fx-font-size: cfg.$font-title-4;
  }
}

.table-view {

  @include _generic-table();

  &.bordered {
    .table-row-cell>.table-cell {
      -fx-border-color: transparent -color-cell-border transparent transparent;

      &:empty {
        -fx-border-color: transparent;
      }
    }
  }

  &.dense {
    >.column-header-background {
      .column-header {
        -fx-size: $header-size-dense;
      }
    }

    .table-row-cell {
      -fx-cell-size: $cell-size-dense;
    }
  }


  &.striped {
    .table-row-cell {
      -fx-background-insets: 0;
    }

    &.bordered {
      .table-row-cell {
        -fx-background-insets: 0, 0 0 1 0;
      }
    }

    .table-row-cell:filled:odd {
      -fx-background-color: -color-cell-border, -color-cell-bg-odd;
    }
  }

  // Add support for NO_HEADER tweak in tables
  &.no-header {
    >.column-header-background {
      -fx-max-height: 0;
      -fx-pref-height: 0;
      -fx-min-height: 0;
    }
  }

  // each row in the table is a .table-row-cell,
  // inside a .table-row-cell is any number of .table-cell
  .table-row-cell {
    -fx-background-color: -color-cell-border, -color-cell-bg;
    -fx-background-insets: 0, 0 0 1 0;
    -fx-padding: 0;
    -fx-cell-size: $cell-size-normal;

    // hide empty rows
    &:empty {
      -fx-background-color: transparent;
      -fx-background-insets: 0;

      >.table-cell {
        -fx-border-color: transparent;
      }
    }

    >.table-cell {
      -fx-padding: 0 $cell-padding-x 0 $cell-padding-x;
      -fx-text-fill: -color-cell-fg;
      -fx-alignment: BASELINE_LEFT;

      // #tweak/align-left
      &.table-column.align-left {
        -fx-alignment: BASELINE_LEFT;
      }

      // #tweak/align-center
      &.table-column.align-center {
        -fx-alignment: BASELINE_CENTER;
      }

      // #tweak/align-right
      &.table-column.align-right {
        -fx-alignment: BASELINE_RIGHT;
      }
    }
  }
}

// when in constrained resize mode, the right-most visible cell should not have a right-border,
// as it is not possible to get this cleanly out of view without introducing horizontal scrollbars
.table-view:constrained-resize>.virtual-flow>.clipped-container>.sheet>.table-row-cell>.table-cell:last-visible,
.tree-table-view:constrained-resize>.virtual-flow>.clipped-container>.sheet>.tree-table-row-cell>.tree-table-cell:last-visible {
  -fx-border-color: transparent;
}

// reset inherited font weight for context menu
.table-view .column-header .context-menu,
.tree-table-view .column-header .context-menu,
.table-view>.column-header-background>.show-hide-columns-button .context-menu,
.tree-table-view>.column-header-background>.show-hide-columns-button .context-menu {
  -fx-font-weight: null;
}

// table cells
.table-view .table-row-cell>.table-cell.check-box-table-cell,
.table-view .table-row-cell>.table-cell.font-icon-table-cell,
.tree-table-view .tree-table-row-cell>.tree-table-cell.check-box-tree-table-cell {
  -fx-alignment: BASELINE_LEFT;
}

///////////////////////////////////////////////////////////////////////////////
//  TreeView                                                                 //
///////////////////////////////////////////////////////////////////////////////

.tree-view {
  @include _base();

  &.dense {
    .tree-cell {
      -fx-padding: $tree-cell-padding-y-dense 0 $tree-cell-padding-y-dense 0;
    }
  }

  &.alt-icon {
    .tree-cell {
      >.tree-disclosure-node {
        -fx-padding: 0.3em $tree-cell-padding-x 0 $tree-cell-padding-x;
      }
    }

    .tree-cell>.tree-disclosure-node>.arrow {
      @include icons.get("chevron-right", false);
      -fx-padding: 0.333333em;
    }

    .tree-cell:expanded>.tree-disclosure-node>.arrow {
      @include icons.get("expand-more", false);
      -fx-padding: 0.333333em;
    }
  }
}

.tree-cell {
  -fx-background-color: -color-cell-bg;
  -fx-text-fill: -color-cell-fg;
  -fx-padding: $tree-cell-padding-y-normal 0 $tree-cell-padding-y-normal 0;
  -fx-indent: $tree-cell-indent;

  // NOTE:
  // Instead of simply applying vertical alignment programmatically the TreeView
  // expects you will do the same thing by adjusting .tree-disclosure-node
  // paddings manually ¯\_(ツ)_/¯. The below values are adjusted for the theme
  // default font size (14px). If you change the font size, you're supposed to
  // re-adjust paddings as well. Also learn about TreeCellSkin#maxDisclosureWidthMap.
  // #javafx-bug
  >.tree-disclosure-node {
    -fx-padding: 0.35em $tree-cell-padding-x 0 $tree-cell-padding-x;
    -fx-background-color: transparent;
  }
}

.tree-cell>.tree-disclosure-node>.arrow,
.tree-table-row-cell>.tree-disclosure-node>.arrow {
  @include icons.get("arrow-right", false);
  -fx-background-color: -color-disclosure;
  -fx-padding: 0.333333em 0.229em 0.333333em 0.229em;
}

.tree-cell:expanded>.tree-disclosure-node>.arrow,
.tree-table-row-cell:expanded>.tree-disclosure-node>.arrow {
  @include icons.get("arrow-drop-down", false);
}

///////////////////////////////////////////////////////////////////////////////
//  TreeTableView                                                            //
///////////////////////////////////////////////////////////////////////////////

// NOTE:
// TreeTableView doesn't play well with editable cells. Whatever column
// you use as first, if it's not ordinary TreeTableCell, there will always
// be some issue with tree disclosure node: alignment, size  etc.
// There's nothing that can be fixed with CSS.
.tree-table-view {

  @include _generic-table();

  &.bordered {
    .tree-table-row-cell>.tree-table-cell {
      -fx-border-color: transparent -color-cell-border transparent transparent;

      &:empty {
        -fx-border-color: transparent;
      }
    }
  }

  &.dense {
    >.column-header-background {
      .column-header {
        -fx-size: $header-size-dense;
      }
    }

    .tree-table-row-cell {
      -fx-cell-size: $cell-size-dense;

      >.tree-disclosure-node {
        -fx-padding: 0.6em $tree-cell-padding-x 0 $tree-cell-padding-x;
      }
    }
  }

  &.striped {
    .tree-table-row-cell {
      -fx-background-insets: 0;
    }

    &.bordered {
      .tree-table-row-cell {
        -fx-background-insets: 0, 0 0 1 0;
      }
    }

    .tree-table-row-cell:filled:odd {
      -fx-background-color: -color-cell-border, -color-cell-bg-odd;
    }
  }

  &.no-header {
    >.column-header-background {
      -fx-max-height: 0;
      -fx-pref-height: 0;
      -fx-min-height: 0;
    }
  }

  .tree-table-row-cell {
    -fx-background-color: -color-cell-border, -color-cell-bg;
    -fx-background-insets: 0, 0 0 1 0;
    -fx-padding: 0;
    -fx-cell-size: $cell-size-normal;
    -fx-indent: 1em;

    // hide empty rows
    &:empty {
      -fx-background-color: transparent;
      -fx-background-insets: 0;
    }

    // read above about disclosure node alignment
    >.tree-disclosure-node {
      -fx-padding: 1em $tree-cell-padding-x 0 $tree-cell-padding-x;
      -fx-background-color: transparent;
    }

    >.tree-table-cell {
      -fx-padding: 0 $cell-padding-x 0 $cell-padding-x;
      -fx-text-fill: -color-cell-fg;
      -fx-alignment: BASELINE_LEFT;

      // #tweak/align-left
      &.table-column.align-left {
        -fx-alignment: BASELINE_LEFT;
      }

      // #tweak/align-center
      &.table-column.align-center {
        -fx-alignment: BASELINE_CENTER;
      }

      // #tweak/align-right
      &.table-column.align-right {
        -fx-alignment: BASELINE_RIGHT;
      }
    }
  }

  &.alt-icon {
    .tree-table-row-cell>.tree-disclosure-node>.arrow {
      @include icons.get("chevron-right", false);
      -fx-padding: 0.333333em;
    }

    .tree-table-row-cell:expanded>.tree-disclosure-node>.arrow {
      @include icons.get("expand-more", false);
      -fx-padding: 0.333333em;
    }
  }
}
